package com.jiangchuang.utils;

import com.google.common.collect.Lists;
import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;

/**
 * @date 2024-07-02 9:22
 */
@Slf4j
@Component
public class MinIoUtil {

    public static MinioClient minioClient;

    @Resource
    private com.jiangchuang.domain.MinioProperties minioProperties;

    public static MinIoUtil minIoUtil;


    /**
     * 初始化minio配置
     */
    @PostConstruct
    public void init() {

        minIoUtil=this;
        minIoUtil.minioProperties=this.minioProperties;
        try {

            minioClient = MinioClient.builder().endpoint(minioProperties.getEndpoint()).credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey()).build();
            createBucket(minioProperties.getBucketName());
            log.info(">>>>>>>>>>>minio 初始化成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error(">>>>>>>>>>>>>>>>初始化minio异常: 【{}】", e.fillInStackTrace());
        }


    }

    /**
     * 判断 bucket是否存在
     *
     * @param bucketName 桶名
     * @return: boolean
     */
    @SneakyThrows(Exception.class)
    public static boolean bucketExists(String bucketName) {
        BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
        return minioClient.bucketExists(bucketArgs);
    }

    /**
     * 创建 bucket
     * @param bucketName 桶名
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public static void createBucket(String bucketName) {
        BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
        boolean isExist = minioClient.bucketExists(bucketArgs);
        if (!isExist) {
            MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
            minioClient.makeBucket(makeBucketArgs);
        }
    }

    /**
     * 获取全部bucket
     * @return: java.util.List
     */
    @SneakyThrows(Exception.class)
    public static List<Bucket> getAllBuckets() {
        return minioClient.listBuckets();
    }

    /**
     * 获取全部bucket下的文件
     * @return: java.util.List
     */
    @SneakyThrows(Exception.class)
    public static List<String> getAllObjects(String bucket, String prefix) {
        List<String> objectNames = Lists.newArrayList();
        ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().bucket(bucket).prefix(prefix).build();
        Iterable<Result<Item>> results = minioClient.listObjects(listObjectsArgs);
        Iterator<Result<Item>> iterator = results.iterator();
        while (iterator.hasNext()){
            Result<Item> next = iterator.next();
            Item item = next.get();
            String objectName = item.objectName();
            objectNames.add(objectName);
        }
        return objectNames;
    }

    /**
     * 文件上传
     * @param bucketName 桶名
     * @param fileName 文件名
     * @param filePath 文件路径
     */
    @SneakyThrows(Exception.class)
    public static void upload(String bucketName, String fileName, String filePath) {
        UploadObjectArgs args = UploadObjectArgs.builder().bucket(bucketName).object(fileName).filename(filePath).build();
        minioClient.uploadObject(args);
    }

    /**
     * 文件上传（返回URL下载地址）
     * @param bucketName 桶名
     * @param fileName 文件名
     * @param stream 文件流
     * @return: 文件url下载地址
     */
    @SneakyThrows(Exception.class)
    public static String upload(String bucketName, String fileName, InputStream stream) {
        PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(stream, stream.available(), -1).build();
        minioClient.putObject(args);
        return getFileUrl(bucketName, fileName);
    }

    /**
     * 文件上传 （返回URL下载地址）
     * @param bucketName 桶名
     * @param file 文件
     * @return: 文件url下载地址
     */
//    @SneakyThrows(Exception.class)
//    public static String upload(String bucketName, MultipartFile file) {
//        final InputStream is = file.getInputStream();
//        final String fileName = file.getOriginalFilename();
////        PutObjectArgs args = PutObjectArgs.builder().stream(file.getInputStream(),file.getSize(),PutObjectArgs.MIN_MULTIPART_SIZE)
//        is.close();
//        return getFileUrl(bucketName, fileName);
//    }

    /**
     * 删除minio文件
     * @param bucketName 桶名
     * @param fileName 文件名
     */
    @SneakyThrows(Exception.class)
    public static void deleteFile(String bucketName, String fileName) {
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build();
        minioClient.removeObject(removeObjectArgs);
    }

    /**
     * 删除文件
     */
    @SneakyThrows(Exception.class)
    public static void deleteFile(String url) {
        // 判断原图在minio还是oss
        if(url.contains("https://sanshipu.jianguijizhang.com/minio/")){
            String[] splitStr = url.split(Global.getMinioPrefix(minIoUtil.minioProperties.getBucketName()));

            if(splitStr.length<=1){
                return;
            }
            String fileName = splitStr[1];
            deleteFile(minIoUtil.minioProperties.getBucketName(),fileName);
        }else{
            // oss中图片
            boolean res = OssUtils.deleteFile(url);
        }
//        String[] splitStr = url.split(Global.getMinioPrefix(minIoUtil.minioProperties.getBucketName()));
//
//        if(splitStr.length<=1){
//            return;
//        }
//        String fileName = splitStr[1];
//
//        deleteFile(minIoUtil.minioProperties.getBucketName(),fileName);
    }

    /**
     * 下载文件 （流输出）
     * @param bucketName  桶名
     * @param fileName 文件名
     */
//    @SneakyThrows(Exception.class)
//    public static void download(String bucketName, String fileName, HttpServletResponse response) {
//        // 获取对象的元数据
//        StatObjectArgs statObjectArgs = StatObjectArgs.builder().bucket(bucketName).object(fileName).build();
//        final ObjectStat stat = minioClient.statObject(statObjectArgs);
//        response.setContentType(stat.contentType());
//        response.setCharacterEncoding("UTF-8");
//        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
//        GetObjectArgs args = GetObjectArgs.builder().bucket(bucketName).object(fileName).build();
//        InputStream is = minioClient.getObject(args);
//        IOUtils.copy(is, response.getOutputStream());
//        is.close();
//    }

    /**
     *
     * 获取minio文件的下载地址
     * @param bucketName 桶名
     * @param fileName  文件名
     */
    @SneakyThrows(Exception.class)
    public static String getFileUrl(String bucketName, String fileName) {
//        return "http://120.77.169.38:9000/"+bucketName+"/"+fileName;
        return Global.DOMAIN_NAME + "/minio/" + bucketName+"/"+fileName;
    }

    /**
     *
     * 方法用于检查MinIO文件夹是否为空，返回true表示为空，返回false表示不为空
     * @param bucketName 桶名
     * @param folderPath  文件名
     */
    @SneakyThrows(Exception.class)
    public static boolean isFolderEmpty(String bucketName, String folderPath) {
        // 获取文件夹中的对象列表
//            Iterable<Result<Item>> results = minioClient.listObjects(bucketName, folderPath, true);
        Iterable<Result<Item>> results =  getFilesList(bucketName,folderPath,true);
        Iterator<Result<Item>> iterator = results.iterator();

        // 如果对象列表为空，则文件夹为空
        return !iterator.hasNext();
    }


    /**
     * 获取路径下文件列表
     *
     * @param bucketName bucket名称
     * @param prefix 文件名称
     * @param recursive 是否递归查找，如果是false,就模拟文件夹结构查找
     * @return 二进制流
     */
    @SneakyThrows(Exception.class)
    public static Iterable<Result<Item>> getFilesList(String bucketName, String prefix, boolean recursive) {
        return minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());
    }

}
